
--
-- @Modified by: Phuong Tran		#54355102
--				 Krzysztof Mazurek	#72329097
--				 
--	@Lab Section: L2C				
--
-- @Date:		 07/02/2012
--	
--
--
--
--
--
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity datapath is
     port(
	    datapath_in : in std_logic_vector(7 downto 0);
		mux1sel : in std_logic;
		write : in std_logic;
		writenum : in std_logic_vector(2 downto 0);
		readnum : in std_logic_vector(2 downto 0);
		loada : in std_logic;
		loadb : in std_logic;
		mux2sel : in std_logic;
		funct : in std_logic_vector(1 downto 0);
		loadc : in std_logic;
		clk : in std_logic;
		datapath_out : out std_logic_vector(7 downto 0));
end datapath ;


architecture behavioural of datapath is

-- First, define your local signals.  The local signals are the
-- ones that connect the various elements of your datapath.
-- You could use the following, or replace them with your
-- own.

signal mux1out : std_logic_vector(7 downto 0);
signal regfileout : std_logic_vector(7 downto 0);
signal regaout : std_logic_vector(7 downto 0);
signal regbout : std_logic_vector(7 downto 0);
signal mux2out : std_logic_vector(7 downto 0);
signal aluout : std_logic_vector(7 downto 0);
signal regcout : std_logic_vector(7 downto 0);
type REGARRAY is array (7 downto 0) of std_logic_vector(7 downto 0);
signal reg : REGARRAY;  -- the storage for the register file
--Will need to reconsider --type ALUMULTIBITS is array (0 downto 0) of std_logic_vector(15 downto 0); -- multipliplication yields 16 bits, take bottom 8, as per specification
begin

   -- Here, define all the elements of the datapath (muxes, register file,
	-- registers, alu).  My implementation consisted of a number of processes.
	
	
-- Mux1 process: Type 1
process(regcout,datapath_in,mux1sel)
  begin
  case (mux1sel) is
    when '0' => mux1out <= regcout;
    when others => mux1out <= datapath_in;
  end case;
end process;

-- Register file: Type 1 & Type 2
-- Type 1: READ
process(reg,readnum)
  begin
    regfileout <= reg (conv_integer (readnum));
end process;

-- Type 2: WRITE
process(clk)
  begin
    if (clk = '1' and clk'event) then
      if (write = '1') then
        reg (conv_integer (writenum)) <= mux1out;        
      end if;   
    end if; 
end process;

-- register A
process(clk)
	begin
		if (clk = '1' and clk'event) then
			if (loada = '1') then
			regaout <= regfileout;
			end if;
		end if;
	end process;
	
-- register B
process(clk)
	begin
		if (clk = '1' and clk'event) then
			if (loadb = '1') then
			regbout <= regfileout;
			end if;
		end if;
	end process;
	
-- register C
process(clk)
	begin
		if (clk = '1' and clk'event) then
			if (loadc = '1') then
			regcout <= aluout;
			end if;
		end if;
	end process;
	
-- Datapath_out is whatever sits on regcout
datapath_out <= regcout;
	
--mux2
process(mux2sel,regbout)
	begin
		case (mux2sel) is
			when '0' => mux2out <= regbout;
			when others => mux2out <= "00000001";
		end case;
end process;
	
-- The Fun Part - ALU
process(funct,regaout,mux2out)
	variable multinum : std_logic_vector(15 downto 0);
	begin
		case (funct) is
			when "00" => aluout <= regaout AND mux2out;
			when "01" => multinum := (regaout * mux2out);
			             aluout <= multinum(7 downto 0);
			when "10" => aluout <= regaout + mux2out;
			when others => aluout <= regaout - mux2out;
		end case;
	end process;

    


end behavioural;


